package com.iflytek.esb.controller;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.iflytek.esb.service.ConfigService;
import com.iflytek.esb.vo.Database;

@Controller
@RequestMapping("/admin/system")
public class SystemController {

	private static final Database[] DATABASES = new Database[] {
		new Database("h2", 
				"org.h2.Driver", 
				"jdbc:h2:~/.esb/esb_db;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000", 
				"SELECT 1", 
				"H2"
		),
		new Database("mysql", 
				"com.mysql.jdbc.Driver", 
				"jdbc:mysql://localhost:3306/esb_db?useUnicode=true&characterEncoding=utf-8", 
				"SELECT 1", 
				"MYSQL"
		),
		new Database("oracle", 
				"oracle.jdbc.driver.OracleDriver", 
				"jdbc:oracle:thin:@localhost:1521:esb", 
				"SELECT 1 FROM dual", 
				"ORACLE"
		),
		new Database("sqlserver", 
				"com.microsoft.sqlserver.jdbc.SQLServerDriver", 
				"jdbc:sqlserver://localhost;database=esb_db;",
				"SELECT 1", 
				"SQLSERVER2005"
		),
	};
	
	private static final String[] LOG_LEVELS = new String[] {"debug", "info", "warning", "error", "fatal"};
	
	private static final String[] LOG_OUTS = new String[] {"console", "log4j"};

	private static final Logger LOG = Logger.getLogger(SystemController.class);
	
	@Autowired
	private ConfigService configService;
	
	@RequestMapping("database")
	public ModelAndView database() {
		LOG.info("<open database config page>");
		
		ModelAndView mv = new ModelAndView("/system/database");
		mv.addObject("databaseType", configService.getJdbcProperty("database.type"));
		mv.addObject("databaseDriver", configService.getJdbcProperty("database.driver"));
		mv.addObject("databaseUrl", configService.getJdbcProperty("database.url"));
		mv.addObject("databaseUsername", configService.getJdbcProperty("database.username"));
		mv.addObject("databasePassword", configService.getJdbcProperty("database.password"));
		mv.addObject("databaseValidationQuery", configService.getJdbcProperty("database.validation.query"));
		mv.addObject("databaseDialect", configService.getJdbcProperty("database.dialect"));
		
		mv.addObject("databases", DATABASES);
		
		return mv;
	}
	
	@RequestMapping("update/database")
	@ResponseBody
	public Map<String, String> database(String databaseType,
			String databaseDriver,
			String databaseUrl,
			String databaseUsername,
			String databasePassword,
			String databaseValidationQuery,
			String databaseDialect) {
		
		LOG.info("<update database config>");
		Map<String, String> r = new HashMap<String, String>();
		
		try {
			configService.setJdbcProperty("database.type", databaseType);
			configService.setJdbcProperty("database.driver", databaseDriver);
			configService.setJdbcProperty("database.url", databaseUrl);
			configService.setJdbcProperty("database.username", databaseUsername);
			configService.setJdbcProperty("database.password", databasePassword);
			configService.setJdbcProperty("database.validation.query", databaseValidationQuery);
			configService.setJdbcProperty("database.dialect", databaseDialect);
			r.put("result", "ok");
		}
		catch (Exception e) {
			r.put("result", "ng");
			r.put("message", e.getMessage());
		}
		return r;
	}
	
	@RequestMapping("service")
	public ModelAndView service() {
		LOG.info("<open service config page>");
		
		ModelAndView mv = new ModelAndView("/system/service");
		mv.addObject("applicationTitle", configService.getConfigValue("application.title"));
		
		return mv;
	}

	@RequestMapping("update/service")
	@ResponseBody
	public Map<String, String> service(String passwordEncoder, 
			String authenticationHandler, 
			String applicationTitle, 
			String rootAccount) {
		
		LOG.info("<update service config>");
		Map<String, String> r = new HashMap<String, String>();
		
		try {
			configService.setConfigValue("application.title", applicationTitle);
			r.put("result", "ok");
		}
		catch (Exception e) {
			r.put("result", "ng");
			r.put("message", e.getMessage());
		}
		return r;
	}

	@RequestMapping("log")
	public ModelAndView log() {
		LOG.info("<open log config page>");
		
		String rootCategory = configService.getLogProperty("log4j.rootCategory");
		String[] ary = StringUtils.split(rootCategory, ",");
		
		String logLevel = StringUtils.trim(ary[0]);
		String logOut = StringUtils.trim(ary[1]);
		
		ModelAndView mv = new ModelAndView("/system/log");
		mv.addObject("logLevel", logLevel);
		mv.addObject("logOut", logOut);
		
		mv.addObject("verboseLogLevel", configService.getLogProperty("log4j.logger.java.sql"));
		
		mv.addObject("consoleConversionPattern", configService.getLogProperty("log4j.appender.console.layout.ConversionPattern"));
		
		mv.addObject("logfile", configService.getLogProperty("log4j.appender.logfile.File"));
		mv.addObject("logfileConversionPattern", configService.getLogProperty("log4j.appender.logfile.layout.ConversionPattern"));
		
		mv.addObject("logLevels", LOG_LEVELS);
		mv.addObject("logOuts", LOG_OUTS);
		
		return mv;
	}
	
	@RequestMapping("update/log")
	@ResponseBody
	public Map<String, String> log(String logLevel,
			String logOut,
			String verboseLogLevel,
			String consoleConversionPattern,
			String logfile,
			String logfileConversionPattern) {
		
		LOG.info("<update log config>");
		Map<String, String> r = new HashMap<String, String>();
		
		try {
			configService.setLogProperty("log4j.rootCategory", logLevel + "," + logOut);
			configService.setLogProperty("log4j.logger.java.sql", verboseLogLevel);
			
			
			configService.setLogProperty("log4j.appender.console.layout.ConversionPattern", consoleConversionPattern);
			
			configService.setLogProperty("log4j.appender.logfile.File", logfile);
			configService.setLogProperty("log4j.appender.logfile.layout.ConversionPattern", logfileConversionPattern);
			
			r.put("result", "ok");
		}
		catch (Exception e) {
			r.put("result", "ng");
			r.put("message", e.getMessage());
		}
		return r;
	}
}
